package com.tpp.threat_perception_platform.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tpp.threat_perception_platform.dao.HostLogMapper;
import com.tpp.threat_perception_platform.param.MyParam;
import com.tpp.threat_perception_platform.pojo.HostLog;
import com.tpp.threat_perception_platform.response.ResponseResult;
import com.tpp.threat_perception_platform.service.HostLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service
public class HostLogServiceImpl implements HostLogService {
    @Autowired
    private HostLogMapper hostLogMapper;
    @Transactional
    @Override
    public int saveHostLog(HostLog hostLog) {
        // 检查是否存在重复记录
        int duplicateCount = hostLogMapper.checkDuplicate(hostLog.getMacAddress(), hostLog.getTimestamp());
        if (duplicateCount > 0) {
            // 存在重复记录，不插入
            return 0;
        }
        setRiskLevel(hostLog);
        // 插入新记录
//        return hostLogMapper.insertSelective(hostLog);
        try {
            // 插入新记录
            return hostLogMapper.insertSelective(hostLog);
        } catch (Exception e) {
            // 记录异常信息
            e.printStackTrace();
            return 0;
        }
    }
    private void setRiskLevel(HostLog hostLog) {
        String eventIdStr = hostLog.getEventId().toString();
        // 规则1: 当event_id是1102删除日志,4634注销系统,4738用户密码更给或重置
        if ("1102".equals(eventIdStr)) {
            hostLog.setRiskLevel("高");
            return;
        }


        if ("4738".equals(eventIdStr)) {
            hostLog.setRiskLevel("中");
            return;
        }
        if ("4625".equals(eventIdStr)) {
            hostLog.setRiskLevel("中");
            return;
        }
        if ("4722".equals(eventIdStr)) {
            hostLog.setRiskLevel("中");
            return;
        }
        // 获取data字段内容并解析出用户名
        String dataJson = hostLog.getData();
        String username = extractUsernameFromData(dataJson);
        // 规则2: 在北京时间凌晨3：00 - 4:00登录就标注风险
        Date timestamp = hostLog.getTimestamp();
        if (timestamp != null) {
            // 将java.util.Date转换为ZonedDateTime，使用北京时间(Asia/Shanghai)
            Instant instant = timestamp.toInstant();
            ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Asia/Shanghai"));
            LocalTime localTime = zonedDateTime.toLocalTime();

            // 检查时间是否在3:00-4:00之间
            if (localTime.isAfter(LocalTime.of(3, 0)) && localTime.isBefore(LocalTime.of(4, 0))) {
                // 这里需要检查同一个用户是否总是在这个时间段登录
                // 为了简化，我们假设直接标注风险
                hostLog.setRiskLevel("中");
                return;
            }
//            //规则3，短时间内多次登录错误
//            if ("4625".equals(eventIdStr) && username != null) {
//                if (isFrequentFailedLogins(username, hostLog.getTimestamp())) {
//                    hostLog.setRiskLevel("高");
//                    return;
//                }
//            }
            // 规则4: 删除用户事件（4726）标注风险
            if ("4726".equals(eventIdStr)) {
                hostLog.setRiskLevel("高");
                return;
            }
        }

        hostLog.setRiskLevel("低");
    }
    /**
     * 从JSON格式的data字段中提取用户名
     */
    private String extractUsernameFromData(String dataJson) {
        if (dataJson == null || dataJson.isEmpty()) {
            return null;
        }

        // 简单方式提取 TargetUserName 或 SubjectUserName（可根据实际结构优化）
        if (dataJson.contains("\"TargetUserName\":\"")) {
            int start = dataJson.indexOf("\"TargetUserName\":\"") + "\"TargetUserName\":\"".length();
            int end = dataJson.indexOf("\"", start);
            return dataJson.substring(start, end);
        } else if (dataJson.contains("\"SubjectUserName\":\"")) {
            int start = dataJson.indexOf("\"SubjectUserName\":\"") + "\"SubjectUserName\":\"".length();
            int end = dataJson.indexOf("\"", start);
            return dataJson.substring(start, end);
        }

        return null;
    }
    /**
     * 判断用户在最近5分钟内是否有超过3次失败登录记录
     */
    private boolean isFrequentFailedLogins(String username, Date currentTimestamp) {
        if (username == null || currentTimestamp == null) {
            return false;
        }

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentTimestamp);
        calendar.add(Calendar.MINUTE, -5); // 计算5分钟前的时间
        Date fiveMinutesAgo = calendar.getTime();

        int failedCount = hostLogMapper.countFailedLoginsInTimeRange(username, fiveMinutesAgo, currentTimestamp);
        return failedCount >= 3;
    }
    @Override
    public ResponseResult hostLogList(MyParam param) {
        // 设置分页参数
        PageHelper.startPage(param.getPage(), param.getLimit());
        // 查询所有
        List<HostLog> dataList = hostLogMapper.findAll(param);

        // 构架pageInfo
        PageInfo<HostLog> pageInfo = new PageInfo<>(dataList);

        return new ResponseResult<>(pageInfo.getTotal(), pageInfo.getList());
    }

    @Override
    public ResponseResult hostLoginLogList(MyParam param) {
        // 设置分页参数
        PageHelper.startPage(param.getPage(), param.getLimit());
        // 查询所有
        List<HostLog> dataList = hostLogMapper.findAllLoginLog(param);

        // 构架pageInfo
        PageInfo<HostLog> pageInfo = new PageInfo<>(dataList);

        return new ResponseResult<>(pageInfo.getTotal(), pageInfo.getList());
    }

    @Override
    public ResponseResult hostAccountLogList(MyParam param) {
        // 设置分页参数
        PageHelper.startPage(param.getPage(), param.getLimit());
        // 查询所有
        List<HostLog> dataList = hostLogMapper.findAllAccountLog(param);

        // 构架pageInfo
        PageInfo<HostLog> pageInfo = new PageInfo<>(dataList);

        return new ResponseResult<>(pageInfo.getTotal(), pageInfo.getList());
    }
}
